Apply the same fixes and improvements as to the gtk-1-3-win32-production
authorTor Lillqvist <tml@iki.fi>
Thu, 10 Jan 2002 00:53:39 +0000 (00:53 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Thu, 10 Jan 2002 00:53:39 +0000 (00:53 +0000)
2002-01-10  Tor Lillqvist  <tml@iki.fi>

Apply the same fixes and improvements as to the
gtk-1-3-win32-production branch: Bug fixes and cleanup of
selection and DND functionality. Still doesn't work as well as the
win32-production branch, though, but getting closer.

After this, need to add Archaeopteryx Software's OLE2 DND support.

* gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
gdk_selection_send_notify, generate_selection_notify): Don't use
SendMessage() to generate events for the same app, instead use
gdk_event_put().

* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c
* gdk/win32/gdkmain-win32.c
* gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
initialisation and handling of gdk_selection_notify_msg,
gdk_selection_request_msg and gdk_selection_clear_msg.

* gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
gdk_free_text_list, gdk_string_to_compound_text,
gdk_free_compound_text): Implement trivially, witrh a text_list
always having a single element, and a compound text always
consisting of just a single (UTF-8!) string. Let's see how well
this works.

* gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
non-ASCII paste from the clipboard: Try getting the same formats
from the Windows clipboard that gdk_property_change() puts there:
CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.

* gdk/win32/gdkproperty-win32.c (gdk_property_change): When
storing text on the clipboard, handle non-ASCII text
correctly. The logic is as follows:

If we have only ASCII characters, use CF_TEXT.

Else, if we are on NT, use CF_UNICODETEXT.

Else (we are on Win9x), if all the characters are present in the
code page of some installed locale, use CF_TEXT and also set
CF_LOCALE to that locale.

Else (still on Win9x) store as RTF. We use a very simple RTF
string, just the text, no fonts or other crap, with the non-ASCII
characters as Unicode \uN keywords. Additionally, also store the
UTF-8 string as such, under the format "UTF8_STRING", so that GDK
can also paste from the Clipboard what it has copied there. (Thus
no need to implement any RTF parser.)

(find_common_locale): New function, implements the search for a
locale for case 3 above.

* gdk/win32/gdkglobals-win32.c: New global variables
compound_text, text_uri_list, utf8_string, cf_rtf and
cf_utf8_string.

* gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
converts from a wchar_t string to UTF-8.
(_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
(_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.

* gdk/win32/gdkevents-win32.c (build_keypress_event): Use
_gdk_ucs2_to_utf8().

* gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.

* gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
gdk_drag_context_ref() was called unnecessarily in a couple of
places, meaning drag contexts were never freed. The same memory
leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.

(gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
stored file list.

* gdk/win32/gdkselection-win32.c: Clarify the use of the
sel_prop_table. Now it is used only for storing the GDK_SELECTION
"properties".

The file names dropped with WM_DROPFILES -style DND is stored
temporarily (between the drop and the target picking them up) in a
separate place.

Have a separate hash table to map selection atoms to owner
windows. This used to be quite mixed up.

(_gdk_dropfiles_store): New function, to store the dropped file
list for the drop target to possibly fetch, and clear it
afterwards, from gdk_drop_reply().

(gdk_selection_owner_get): Much simplified now.

18 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/win32/gdkdnd-win32.c
gdk/win32/gdkdrawable-win32.c
gdk/win32/gdkevents-win32.c
gdk/win32/gdkfont-win32.c
gdk/win32/gdkglobals-win32.c
gdk/win32/gdkim-win32.c
gdk/win32/gdkmain-win32.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkproperty-win32.c
gdk/win32/gdkselection-win32.c
gdk/win32/gdkwindow-win32.c

index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 66b608339b4b1059dbe713e26c3986475d69a2b8..5a5f0ef172af8be288d59a03086d3b5df0deb20f 100644 (file)
@@ -1,3 +1,97 @@
+2002-01-10  Tor Lillqvist  <tml@iki.fi>
+
+       Apply the same fixes and improvements as to the
+       gtk-1-3-win32-production branch: Bug fixes and cleanup of
+       selection and DND functionality. Still doesn't work as well as the
+       win32-production branch, though, but getting closer.
+
+       After this, need to add Archaeopteryx Software's OLE2 DND support.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_owner_set,
+       gdk_selection_send_notify, generate_selection_notify): Don't use
+       SendMessage() to generate events for the same app, instead use
+       gdk_event_put().
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c
+       * gdk/win32/gdkmain-win32.c
+       * gdk/win32/gdkevents-win32.c: Thus, remove declaration, definition,
+       initialisation and handling of gdk_selection_notify_msg,
+       gdk_selection_request_msg and gdk_selection_clear_msg. 
+
+       * gdk/win32/gdkselection-win32.c (gdk_text_property_to_text_list,
+       gdk_free_text_list, gdk_string_to_compound_text,
+       gdk_free_compound_text): Implement trivially, witrh a text_list
+       always having a single element, and a compound text always
+       consisting of just a single (UTF-8!) string. Let's see how well
+       this works.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert): Fix
+       non-ASCII paste from the clipboard: Try getting the same formats
+       from the Windows clipboard that gdk_property_change() puts there:
+       CF_UNICODETEXT, UTF8_STRING or CF_TEXT+CF_LOCALE.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change): When
+       storing text on the clipboard, handle non-ASCII text
+       correctly. The logic is as follows:
+
+       If we have only ASCII characters, use CF_TEXT.
+
+       Else, if we are on NT, use CF_UNICODETEXT.
+
+       Else (we are on Win9x), if all the characters are present in the
+       code page of some installed locale, use CF_TEXT and also set
+       CF_LOCALE to that locale.
+
+       Else (still on Win9x) store as RTF. We use a very simple RTF
+       string, just the text, no fonts or other crap, with the non-ASCII
+       characters as Unicode \uN keywords. Additionally, also store the
+       UTF-8 string as such, under the format "UTF8_STRING", so that GDK
+       can also paste from the Clipboard what it has copied there. (Thus
+       no need to implement any RTF parser.)
+       
+       (find_common_locale): New function, implements the search for a
+       locale for case 3 above.
+
+       * gdk/win32/gdkglobals-win32.c: New global variables
+       compound_text, text_uri_list, utf8_string, cf_rtf and
+       cf_utf8_string.
+
+       * gdk/win32/gdkim-win32.c (_gdk_ucs2_to_utf8): New function,
+       converts from a wchar_t string to UTF-8.
+       (_gdk_utf8_to_ucs2): Rename from _gdk_win32_nmbstowchar_ts.
+       (_gdk_utf8_to_wcs): Rename from gdk_nmbstowchar_ts.
+
+       * gdk/win32/gdkevents-win32.c (build_keypress_event): Use
+       _gdk_ucs2_to_utf8().
+
+       * gdk/win32/gdkselection-win32.c: Remove some unnecessary logging.
+
+       * gdk/win32/gdkdnd-win32.c: Plug memory leaks, the
+       gdk_drag_context_ref() was called unnecessarily in a couple of
+       places, meaning drag contexts were never freed. The same memory
+       leaks seem to be present in gdk/linux-fb/gdkselection-fb.c, BTW.
+
+       (gdk_drop_reply): For WIN32_DROPFILES drops, free the temporarily
+       stored file list.
+
+       * gdk/win32/gdkselection-win32.c: Clarify the use of the
+       sel_prop_table. Now it is used only for storing the GDK_SELECTION
+       "properties".
+
+       The file names dropped with WM_DROPFILES -style DND is stored
+       temporarily (between the drop and the target picking them up) in a
+       separate place.
+
+       Have a separate hash table to map selection atoms to owner
+       windows. This used to be quite mixed up.
+
+       (_gdk_dropfiles_store): New function, to store the dropped file
+       list for the drop target to possibly fetch, and clear it
+       afterwards, from gdk_drop_reply().
+
+       (gdk_selection_owner_get): Much simplified now.
+
 2002-01-09  jacob berkman  <jacob@ximian.com>
 
        * gtk/gtklayout.c (gtk_layout_style_set): set the background of
index 04883fccedd204b3191a13b8898cafbf2394729c..33a13a66edd7046ec2ec1b462b6406ac198c8a96 100644 (file)
@@ -1,6 +1,6 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-1999 Tor Lillqvist
+ * Copyright (C) 1998-2002 Tor Lillqvist
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -87,7 +87,6 @@ static int nformats;
  * this is used on both source and destination sides.
  */
 struct _GdkDragContextPrivateWin32 {
-  GdkAtom local_selection;
   gint    ref_count;
 
   guint16 last_x;              /* Coordinates from last event */
@@ -192,6 +191,8 @@ gdk_drag_context_ref (GdkDragContext *context)
 {
   g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
+  GDK_NOTE (DND, g_print ("gdk_drag_context_ref: %p %d\n", context, G_OBJECT(context)->ref_count));
+
   g_object_ref (G_OBJECT (context));
 }
 
@@ -200,16 +201,16 @@ gdk_drag_context_unref (GdkDragContext *context)
 {
   g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
+  GDK_NOTE (DND, g_print ("gdk_drag_context_unref: %p %d\n", context, G_OBJECT(context)->ref_count));
   g_object_unref (G_OBJECT (context));
 }
 
 static GdkDragContext *
-gdk_drag_context_find (gboolean     is_source,
-                      GdkWindow   *source,
-                      GdkWindow   *dest)
+gdk_drag_context_find (gboolean   is_source,
+                      GdkWindow *source,
+                      GdkWindow *dest)
 {
   GList *tmp_list = contexts;
-  
   GdkDragContext *context;
   GdkDragContextPrivateWin32 *private;
 
@@ -221,7 +222,7 @@ gdk_drag_context_find (gboolean     is_source,
       if ((!context->is_source == !is_source) &&
          ((source == NULL) || (context->source_window && (context->source_window == source))) &&
          ((dest == NULL) || (context->dest_window && (context->dest_window == dest))))
-         return context;
+       return context;
       
       tmp_list = tmp_list->next;
     }
@@ -943,7 +944,6 @@ gdk_dropfiles_filter (GdkXEvent *xev,
 {
   GdkDragContext *context;
   GdkDragContextPrivateWin32 *private;
-  static GdkAtom text_uri_list_atom = GDK_NONE;
   GString *result;
   MSG *msg = (MSG *) xev;
   HANDLE hdrop;
@@ -951,9 +951,6 @@ gdk_dropfiles_filter (GdkXEvent *xev,
   gint nfiles, i;
   guchar fileName[MAX_PATH], linkedFile[MAX_PATH];
   
-  if (text_uri_list_atom == GDK_NONE)
-    text_uri_list_atom = gdk_atom_intern ("text/uri-list", FALSE);
-
   if (msg->message == WM_DROPFILES)
     {
       GDK_NOTE (DND, g_print ("WM_DROPFILES: %#x\n", (guint) msg->hwnd));
@@ -968,12 +965,11 @@ gdk_dropfiles_filter (GdkXEvent *xev,
       gdk_drawable_ref (context->dest_window);
       /* WM_DROPFILES drops are always file names */
       context->targets =
-       g_list_append (NULL, GUINT_TO_POINTER (text_uri_list_atom));
+       g_list_append (NULL, GUINT_TO_POINTER (text_uri_list));
       current_dest_drag = context;
 
       event->dnd.type = GDK_DROP_START;
       event->dnd.context = current_dest_drag;
-      gdk_drag_context_ref (current_dest_drag);
       
       hdrop = (HANDLE) msg->wParam;
       DragQueryPoint (hdrop, &pt);
@@ -1005,8 +1001,8 @@ gdk_dropfiles_filter (GdkXEvent *xev,
            }
          g_string_append (result, "\015\012");
        }
-      _gdk_selection_property_store (_gdk_parent_root, text_uri_list_atom, 8,
-                         result->str, result->len + 1);
+      _gdk_dropfiles_store (result->str);
+      g_string_free (result, FALSE);
 
       DragFinish (hdrop);
       
@@ -1058,8 +1054,8 @@ _gdk_win32_dnd_exit (void)
 /* Source side */
 
 static void
-local_send_leave (GdkDragContext  *context,
-                 guint32          time)
+local_send_leave (GdkDragContext *context,
+                 guint32         time)
 {
   GdkEvent tmp_event;
   
@@ -1070,20 +1066,19 @@ local_send_leave (GdkDragContext  *context,
       tmp_event.dnd.type = GDK_DRAG_LEAVE;
       tmp_event.dnd.window = context->dest_window;
       /* Pass ownership of context to the event */
-      tmp_event.dnd.context = current_dest_drag;
       tmp_event.dnd.send_event = FALSE;
+      tmp_event.dnd.context = current_dest_drag;
       tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
 
       current_dest_drag = NULL;
       
       gdk_event_put (&tmp_event);
     }
-  
 }
 
 static void
-local_send_enter (GdkDragContext  *context,
-                 guint32          time)
+local_send_enter (GdkDragContext *context,
+                 guint32         time)
 {
   GdkEvent tmp_event;
   GdkDragContextPrivateWin32 *private;
@@ -1091,9 +1086,6 @@ local_send_enter (GdkDragContext  *context,
 
   private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
   
-  if (!private->local_selection)
-    private->local_selection = gdk_atom_intern ("LocalDndSelection", FALSE);
-
   if (current_dest_drag != NULL)
     {
       gdk_drag_context_unref (current_dest_drag);
@@ -1109,7 +1101,6 @@ local_send_enter (GdkDragContext  *context,
   new_context->dest_window = context->dest_window;
   gdk_window_ref (new_context->dest_window);
 
-
   new_context->targets = g_list_copy (context->targets);
 
   gdk_window_set_events (new_context->source_window,
@@ -1121,24 +1112,19 @@ local_send_enter (GdkDragContext  *context,
   tmp_event.dnd.window = context->dest_window;
   tmp_event.dnd.send_event = FALSE;
   tmp_event.dnd.context = new_context;
-  gdk_drag_context_ref (new_context);
-
   tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
   
   current_dest_drag = new_context;
   
-  (GDK_DRAG_CONTEXT_PRIVATE_DATA (new_context))->local_selection = 
-    private->local_selection;
-
   gdk_event_put (&tmp_event);
 }
 
 static void
-local_send_motion (GdkDragContext  *context,
-                   gint            x_root, 
-                   gint            y_root,
-                   GdkDragAction   action,
-                   guint32         time)
+local_send_motion (GdkDragContext *context,
+                  gint            x_root, 
+                  gint            y_root,
+                  GdkDragAction   action,
+                  guint32         time)
 {
   GdkEvent tmp_event;
   
@@ -1150,8 +1136,6 @@ local_send_motion (GdkDragContext  *context,
       tmp_event.dnd.window = current_dest_drag->dest_window;
       tmp_event.dnd.send_event = FALSE;
       tmp_event.dnd.context = current_dest_drag;
-      gdk_drag_context_ref (current_dest_drag);
-
       tmp_event.dnd.time = time;
 
       current_dest_drag->suggested_action = action;
@@ -1170,7 +1154,8 @@ local_send_motion (GdkDragContext  *context,
 }
 
 static void
-local_send_drop (GdkDragContext *context, guint32 time)
+local_send_drop (GdkDragContext *context,
+                guint32         time)
 {
   GdkEvent tmp_event;
   
@@ -1184,10 +1169,7 @@ local_send_drop (GdkDragContext *context, guint32 time)
       tmp_event.dnd.type = GDK_DROP_START;
       tmp_event.dnd.window = current_dest_drag->dest_window;
       tmp_event.dnd.send_event = FALSE;
-
       tmp_event.dnd.context = current_dest_drag;
-      gdk_drag_context_ref (current_dest_drag);
-
       tmp_event.dnd.time = GDK_CURRENT_TIME;
       
       tmp_event.dnd.x_root = private->last_x;
@@ -1314,7 +1296,6 @@ gdk_drag_get_protocol (guint32          xid,
 
   window = gdk_window_lookup (xid);
 
-
   if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
     {
       *protocol = GDK_DRAG_PROTO_LOCAL;
@@ -1355,7 +1336,6 @@ gdk_drag_find_window (GdkDragContext  *context,
   GDK_NOTE (DND, g_print ("gdk_drag_find_window: %#x +%d+%d Protocol: %d\n",
                          (drag_window ? (guint) GDK_WINDOW_HWND (drag_window) : 0),
                          x_root, y_root, *protocol));
-
 }
 
 gboolean
@@ -1397,7 +1377,6 @@ gdk_drag_motion (GdkDragContext *context,
              local_send_enter (context, time);
              break;
 
-
            default:
              break;
            }
@@ -1448,6 +1427,7 @@ gdk_drag_motion (GdkDragContext *context,
            case GDK_DRAG_PROTO_NONE:
              g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_motion()");
              break;
+
            default:
              break;
            }
@@ -1478,6 +1458,7 @@ gdk_drag_drop (GdkDragContext *context,
        case GDK_DRAG_PROTO_NONE:
          g_warning ("GDK_DRAG_PROTO_NONE is not valid in gdk_drag_drop()");
          break;
+
        default:
          break;
        }
@@ -1525,8 +1506,6 @@ gdk_drag_status (GdkDragContext *context,
       tmp_event.dnd.window = context->source_window;
       tmp_event.dnd.send_event = FALSE;
       tmp_event.dnd.context = src_context;
-      gdk_drag_context_ref (src_context);
-
       tmp_event.dnd.time = GDK_CURRENT_TIME; /* FIXME? */
 
       if (action == GDK_ACTION_DEFAULT)
@@ -1546,6 +1525,19 @@ gdk_drop_reply (GdkDragContext *context,
   g_return_if_fail (context != NULL);
 
   GDK_NOTE (DND, g_print ("gdk_drop_reply\n"));
+
+  if (context->dest_window)
+    {
+      switch (context->protocol)
+       {
+       case GDK_DRAG_PROTO_WIN32_DROPFILES:
+         _gdk_dropfiles_store (NULL);
+         break;
+
+       default:
+         break;
+       }
+    }
 }
 
 void
@@ -1572,7 +1564,6 @@ gdk_drop_finish (GdkDragContext *context,
       tmp_event.dnd.window = src_context->source_window;
       tmp_event.dnd.send_event = FALSE;
       tmp_event.dnd.context = src_context;
-      gdk_drag_context_ref (src_context);
 
       gdk_event_put (&tmp_event);
     }
@@ -1614,8 +1605,8 @@ gdk_window_register_dnd (GdkWindow *window)
 
   if (GPOINTER_TO_INT (gdk_drawable_get_data (window, "gdk-dnd-registered")))
     return;
-  else
-    gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
+
+  gdk_drawable_set_data (window, "gdk-dnd-registered", GINT_TO_POINTER(TRUE), NULL);
 
   GDK_NOTE (DND, g_print ("gdk_window_register_dnd: %#x\n",
                          (guint) GDK_WINDOW_HWND (window)));
@@ -1668,11 +1659,11 @@ GdkAtom
 gdk_drag_get_selection (GdkDragContext *context)
 {
   if (context->protocol == GDK_DRAG_PROTO_LOCAL)
-    return (GDK_DRAG_CONTEXT_PRIVATE_DATA (context))->local_selection;
+    return local_dnd;
   else if (context->protocol == GDK_DRAG_PROTO_WIN32_DROPFILES)
-    return gdk_win32_dropfiles_atom;
+    return gdk_win32_dropfiles;
   else if (context->protocol == GDK_DRAG_PROTO_OLE2)
-    return gdk_ole2_dnd_atom;
+    return gdk_ole2_dnd;
   else
     return GDK_NONE;
 }
index 4f94df3299dfabff80de70911d09bc8b8ca7b9b3..e42b3426c10ffa86ce271fc4cf5d86972438196c 100644 (file)
@@ -554,8 +554,8 @@ gdk_win32_draw_text (GdkDrawable *drawable,
   else
     {
       wcstr = g_new (wchar_t, text_length);
-      if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
-       g_warning ("gdk_win32_draw_text: _gdk_win32_nmbstowchar_ts failed");
+      if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
+       g_warning ("gdk_win32_draw_text: _gdk_utf8_to_ucs2 failed");
       else
        _gdk_wchar_text_handle (font, wcstr, wlen, gdk_draw_text_handler, &arg);
       g_free (wcstr);
index 3c8a0af8a2f1415d1ba66683bac5ace40a70593e..0a0bbd0c5b93d2bb9e2ac9fb8a409b779fd0a893 100644 (file)
@@ -840,9 +840,9 @@ build_keypress_event (GdkWindowImplWin32 *impl,
                      MSG                *msg)
 {
   HIMC himc;
-  gint i, bytecount, ucount, ucleft, len;
-  guchar buf[100], *bp;
-  wchar_t wbuf[100], *wcp;
+  gint i, bytecount, ucount;
+  guchar buf[100];
+  wchar_t wbuf[100];
 
   event->key.type = GDK_KEY_PRESS;
   event->key.time = msg->time;
@@ -889,8 +889,7 @@ build_keypress_event (GdkWindowImplWin32 *impl,
        */
       ucount = MultiByteToWideChar (impl->charset_info.ciACP,
                                    0, buf, bytecount,
-                                   wbuf, sizeof (wbuf) / sizeof (wbuf[0]));
-      
+                                   wbuf, G_N_ELEMENTS (wbuf));
     }
   if (ucount == 0)
     event->key.keyval = GDK_VoidSymbol;
@@ -911,68 +910,18 @@ build_keypress_event (GdkWindowImplWin32 *impl,
   build_key_event_state (event);
 
   /* Build UTF-8 string */
-  ucleft = ucount;
-  len = 0;
-  wcp = wbuf;
-  while (ucleft-- > 0)
+  if (ucount == 1 && wbuf[0] < 0200)
     {
-      wchar_t c = *wcp++;
-
-      if (c < 0x80)
-       len += 1;
-      else if (c < 0x800)
-       len += 2;
-      else
-       len += 3;
+      event->key.string = g_malloc (2);
+      event->key.string[0] = wbuf[0];
+      event->key.string[1] = '\0';
+      event->key.length = 1;
     }
-
-  event->key.string = g_malloc (len + 1);
-  event->key.length = len;
-  
-  ucleft = ucount;
-  wcp = wbuf;
-  bp = event->key.string;
-  while (ucleft-- > 0)
+  else
     {
-      int first;
-      wchar_t c = *wcp++;
-
-      if (c < 0x80)
-       {
-         first = 0;
-         len = 1;
-       }
-      else if (c < 0x800)
-       {
-         first = 0xc0;
-         len = 2;
-       }
-      else
-       {
-         first = 0xe0;
-         len = 3;
-       }
-
-#if 1      
-      /* Woo-hoo! */
-      switch (len)
-       {
-       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
-       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
-       case 1: bp[0] = c | first;
-       }
-#else
-      for (i = len - 1; i > 0; --i)
-       {
-         bp[i] = (c & 0x3f) | 0x80;
-         c >>= 6;
-       }
-      bp[0] = c | first;
-#endif
-
-      bp += len;
+      event->key.string = _gdk_ucs2_to_utf8 (wbuf, ucount);
+      event->key.length = strlen (event->key.string);
     }
-  *bp = 0;
 }
 
 static void
@@ -1647,55 +1596,7 @@ gdk_event_translate (GdkEvent *event,
   /* to translate coordinates to the internal > 16 bit system */
   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
-  if (msg->message == gdk_selection_notify_msg)
-    {
-      GDK_NOTE (EVENTS, g_print ("gdk_selection_notify_msg: %#lx\n",
-                                (gulong) msg->hwnd));
-
-      event->selection.type = GDK_SELECTION_NOTIFY;
-      event->selection.window = window;
-      event->selection.selection = GDK_POINTER_TO_ATOM (msg->wParam);
-      event->selection.target = GDK_POINTER_TO_ATOM (msg->lParam);
-      event->selection.property = _gdk_selection_property;
-      event->selection.time = msg->time;
-
-      return_val = !GDK_WINDOW_DESTROYED (window);
-
-      goto done;
-    }
-  else if (msg->message == gdk_selection_request_msg)
-    {
-      GDK_NOTE (EVENTS, g_print ("gdk_selection_request_msg: %#lx\n",
-                                (gulong) msg->hwnd));
-
-      event->selection.type = GDK_SELECTION_REQUEST;
-      event->selection.window = window;
-      event->selection.selection = gdk_clipboard_atom;
-      event->selection.target = GDK_TARGET_STRING;
-      event->selection.property = _gdk_selection_property;
-      event->selection.requestor = (guint32) msg->hwnd;
-      event->selection.time = msg->time;
-
-      return_val = !GDK_WINDOW_DESTROYED (window);
-
-      goto done;
-    }
-  else if (msg->message == gdk_selection_clear_msg)
-    {
-      GDK_NOTE (EVENTS, g_print ("gdk_selection_clear_msg: %#lx\n",
-                                (gulong) msg->hwnd));
-
-      event->selection.type = GDK_SELECTION_CLEAR;
-      event->selection.window = window;
-      event->selection.selection = GDK_POINTER_TO_ATOM (msg->wParam);
-      event->selection.target = GDK_POINTER_TO_ATOM (msg->lParam);
-      event->selection.time = msg->time;
-
-      return_val = !GDK_WINDOW_DESTROYED (window);
-
-      goto done;
-    }
-  else if (msg->message == msh_mousewheel_msg)
+  if (msg->message == msh_mousewheel_msg)
     {
       GDK_NOTE (EVENTS, g_print ("MSH_MOUSEWHEEL: %#lx %d\n",
                                 (gulong) msg->hwnd, msg->wParam));
index 264c160b89c99761fa6ce67cf7c925a716886434..c7cde75a2e27b50363b4c6d52b0e130b403cd14b 100644 (file)
@@ -1907,8 +1907,8 @@ gdk_text_size (GdkFont           *font,
     }
   else
     {
-      if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
-       g_warning ("gdk_text_size: _gdk_win32_nmbstowchar_ts failed");
+      if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
+       g_warning ("gdk_text_size: _gdk_utf8_to_ucs2 failed");
       else
        _gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg);
     }
@@ -2014,8 +2014,8 @@ gdk_text_extents (GdkFont     *font,
     }
   else
     {
-      if ((wlen = _gdk_win32_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
-       g_warning ("gdk_text_extents: _gdk_win32_nmbstowchar_ts failed");
+      if ((wlen = _gdk_utf8_to_ucs2 (wcstr, text, text_length, text_length)) == -1)
+       g_warning ("gdk_text_extents: _gdk_utf8_to_ucs2 failed");
       else
        _gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg);
     }
index 6deedaf6260f695e69557369d5664b15204115da..6a6a248d0fbe0c59aad93e3caac3ba4faa0764fa 100644 (file)
 #include "gdkprivate-win32.h"
 
 HWND              gdk_root_window = NULL;
-gint              gdk_event_func_from_window_proc = FALSE;
 HDC              gdk_display_hdc;
 HINSTANCE        gdk_dll_hinstance;
 HINSTANCE        gdk_app_hmodule;
-UINT             gdk_selection_notify_msg;
-UINT             gdk_selection_request_msg;
-UINT             gdk_selection_clear_msg;
-GdkAtom                  gdk_clipboard_atom;
-GdkAtom                  gdk_win32_dropfiles_atom;
-GdkAtom                  gdk_ole2_dnd_atom;
+
+WORD             cf_rtf;
+WORD             cf_utf8_string;
+
+GdkAtom           utf8_string;
+GdkAtom                  compound_text;
+GdkAtom                  text_uri_list;
+
+GdkAtom                  local_dnd;
+GdkAtom                  gdk_win32_dropfiles;
+GdkAtom                  gdk_ole2_dnd;
+
 GdkAtom           _gdk_selection_property;
+
 DWORD            windows_version = 0;
+
 gint             gdk_input_ignore_wintab = FALSE;
+gint              gdk_event_func_from_window_proc = FALSE;
index 52b70ab68b05a1303a4d7ac692881cafea882109..40019a2d32a04b74c1243dcedf334b02c181ca5b 100644 (file)
@@ -151,26 +151,77 @@ gdk_wcstombs (const GdkWChar *src)
   return mbstr;
 }
 
+/* A vesion that converts from wchar_t strings to UTF-8 */
+
+gchar *
+_gdk_ucs2_to_utf8 (const wchar_t *src,
+                  gint           src_len)
+{
+  gint len;
+  const wchar_t *wcp;
+  guchar *mbstr, *bp;
+
+  wcp = src;
+  len = 0;
+  while (wcp < src + src_len)
+    {
+      const wchar_t c = *wcp++;
+
+      if (c < 0x80)
+       len += 1;
+      else if (c < 0x800)
+       len += 2;
+      else
+       len += 3;
+    }
+
+  mbstr = g_malloc (len + 1);
   
-/*
- * gdk_mbstowcs
- *
- * Converts the specified string into GDK wide characters, and,
- * returns the number of wide characters written. The string 'src'
- * must be null-terminated. If the conversion is failed, it returns
- * -1.
- *
- * On Win32, the string is assumed to be in UTF-8.  Also note that
- * GdkWChar is 32 bits, while wchar_t, and the wide characters the
- * Windows API uses, are 16 bits!
- */
+  wcp = src;
+  bp = mbstr;
+  while (wcp < src + src_len)
+    {
+      int first;
+      wchar_t c = *wcp++;
 
-/* First a helper function for not zero-terminated strings */
-static gint
-gdk_nmbstowcs (GdkWChar    *dest,
-              const gchar *src,
-              gint         src_len,
-              gint         dest_max)
+      if (c < 0x80)
+       {
+         first = 0;
+         len = 1;
+       }
+      else if (c < 0x800)
+       {
+         first = 0xc0;
+         len = 2;
+       }
+      else
+       {
+         first = 0xe0;
+         len = 3;
+       }
+      
+      /* Woo-hoo! */
+      switch (len)
+       {
+       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 1: bp[0] = c | first;
+       }
+
+      bp += len;
+    }
+  *bp = 0;
+
+  return mbstr;
+}
+  
+/* Convert from UTF-8 to GdkWChar */
+
+gint
+_gdk_utf8_to_wcs (GdkWChar    *dest,
+                 const gchar *src,
+                 gint         src_len,
+                 gint         dest_max)
 {
   guchar *cp, *end;
   gint n;
@@ -240,22 +291,35 @@ gdk_nmbstowcs (GdkWChar    *dest,
   return n;
 }
 
+/*
+ * gdk_mbstowcs
+ *
+ * Converts the specified string into GDK wide characters, and,
+ * returns the number of wide characters written. The string 'src'
+ * must be null-terminated. If the conversion is failed, it returns
+ * -1.
+ *
+ * On Win32, the string is assumed to be in UTF-8.  Also note that
+ * GdkWChar is 32 bits, while wchar_t, and the wide characters the
+ * Windows API uses, are 16 bits!
+ */
+
 gint
 gdk_mbstowcs (GdkWChar    *dest,
              const gchar *src,
              gint         dest_max)
 {
-  return gdk_nmbstowcs (dest, src, strlen (src), dest_max);
+  return _gdk_utf8_to_wcs (dest, src, strlen (src), dest_max);
 }
 
 
-/* A version that converts to wchar_t wide chars */
+/* A version that converts to a wchar_t string */
 
 gint
-_gdk_win32_nmbstowchar_ts (wchar_t     *dest,
-                           const gchar *src,
-                           gint         src_len,
-                           gint         dest_max)
+_gdk_utf8_to_ucs2 (wchar_t     *dest,
+                  const gchar *src,
+                  gint         src_len,
+                  gint         dest_max)
 {
   wchar_t *wcp;
   guchar *cp, *end;
index 73d5461f1bf939774a3ca9650ca13c785a19fbed..54e5eedc0e02cba7427f29597fba132795226047 100644 (file)
@@ -86,14 +86,18 @@ _gdk_windowing_init_check (int    argc,
 
   CoInitialize (NULL);
 
-  gdk_selection_request_msg = RegisterWindowMessage ("gdk-selection-request");
-  gdk_selection_notify_msg = RegisterWindowMessage ("gdk-selection-notify");
-  gdk_selection_clear_msg = RegisterWindowMessage ("gdk-selection-clear");
+  cf_rtf = RegisterClipboardFormat ("Rich Text Format");
+  cf_utf8_string = RegisterClipboardFormat ("UTF8_STRING");
+
+  utf8_string = gdk_atom_intern ("UTF8_STRING", FALSE);
+  compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
+  text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
+
+  local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
+  gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);
+  gdk_ole2_dnd = gdk_atom_intern ("OLE2_DND", FALSE);
 
   _gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
-  gdk_clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
-  gdk_win32_dropfiles_atom = gdk_atom_intern ("DROPFILES_DND", FALSE);
-  gdk_ole2_dnd_atom = gdk_atom_intern ("OLE2_DND", FALSE);
 
   _gdk_win32_selection_init ();
 
index a23847517246fd030ab487e035f1010f7b104c47..e8a2f7b7cdbea64b9a8293a73812a8d8b0560830 100644 (file)
@@ -374,12 +374,12 @@ GdkImage *_gdk_win32_copy_to_image       (GdkDrawable *drawable,
                                          gint         width,
                                          gint         height);
 
-COLORREF _gdk_win32_colormap_color      (GdkColormap        *colormap,
-                                         gulong              pixel);
+COLORREF _gdk_win32_colormap_color       (GdkColormap *colormap,
+                                         gulong       pixel);
 
-HRGN    BitmapToRegion          (HBITMAP hBmp);
+HRGN    BitmapToRegion                  (HBITMAP hBmp);
 
-gchar  *gdk_font_full_name_get   (GdkFont *font);
+gchar   *gdk_font_full_name_get          (GdkFont *font);
 
 void    _gdk_selection_property_store (GdkWindow *owner,
                                        GdkAtom    type,
@@ -389,11 +389,16 @@ void    _gdk_selection_property_store (GdkWindow *owner,
 
 void    _gdk_selection_property_delete (GdkWindow *);
 
-gint    _gdk_win32_nmbstowchar_ts (wchar_t     *dest,
+void    _gdk_dropfiles_store (gchar *data);
+
+gint    _gdk_utf8_to_ucs2         (wchar_t     *dest,
                                    const gchar *src,
                                    gint         src_len,
                                    gint         dest_max);
 
+gchar  *_gdk_ucs2_to_utf8         (const wchar_t *src,
+                                  gint           src_len);
+
 void    _gdk_wchar_text_handle    (GdkFont       *font,
                                   const wchar_t *wcstr,
                                   int            wclen,
@@ -441,26 +446,34 @@ void    gdk_win32_gdi_failed        (const gchar *where,
 extern LRESULT CALLBACK _gdk_win32_window_procedure (HWND, UINT, WPARAM, LPARAM);
 
 extern HWND             gdk_root_window;
-extern gboolean                 gdk_event_func_from_window_proc;
 
 extern HDC              gdk_display_hdc;
 extern HINSTANCE        gdk_dll_hinstance;
 extern HINSTANCE        gdk_app_hmodule;
 
-extern UINT             gdk_selection_notify_msg;
-extern UINT             gdk_selection_request_msg;
-extern UINT             gdk_selection_clear_msg;
-extern GdkAtom          gdk_clipboard_atom;
-extern GdkAtom          gdk_win32_dropfiles_atom;
-extern GdkAtom          gdk_ole2_dnd_atom;
+/* Registered clipboard formats */
+extern WORD             cf_rtf;
+extern WORD             cf_utf8_string;
 
-extern DWORD            windows_version;
-#define IS_WIN_NT()      (windows_version < 0x80000000)
+/* GdkAtoms: Targets */
+extern GdkAtom           utf8_string;
+extern GdkAtom          compound_text;
+extern GdkAtom          text_uri_list;
 
-extern gint             gdk_input_ignore_wintab;
+/* DND selections */
+extern GdkAtom           local_dnd;
+extern GdkAtom          gdk_win32_dropfiles;
+extern GdkAtom          gdk_ole2_dnd;
 
 extern GdkAtom          _gdk_selection_property;
 
+extern DWORD            windows_version;
+#define IS_WIN_NT()      (windows_version < 0x80000000)
+
+/* Options */
+extern gboolean                 gdk_input_ignore_wintab;
+extern gboolean                 gdk_event_func_from_window_proc;
+
 #define IMAGE_PRIVATE_DATA(image) ((GdkImagePrivateWin32 *) GDK_IMAGE (image)->windowing_data)
 
 #endif /* __GDK_PRIVATE_WIN32_H__ */
index caaa13cc6fccde69ad7b5d3920af2e86dae1c694..1609d90ff9845b104959dbf7a4f51081dedd3844 100644 (file)
@@ -1,5 +1,6 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1998-2002 Tor Lillqvist
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,8 @@
  */
 
 #include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #include "gdkproperty.h"
 #include "gdkselection.h"
@@ -34,9 +37,9 @@ GdkAtom
 gdk_atom_intern (const gchar *atom_name,
                 gint         only_if_exists)
 {
+  ATOM win32_atom;
   GdkAtom retval;
   static GHashTable *atom_hash = NULL;
-  ATOM win32_atom;
   
   if (!atom_hash)
     atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
@@ -68,17 +71,12 @@ gdk_atom_intern (const gchar *atom_name,
        retval = GDK_SELECTION_TYPE_STRING;
       else
        {
-         win32_atom = GlobalFindAtom (atom_name);
-         if (only_if_exists && retval == 0)
-           win32_atom = 0;
-         else
-           win32_atom = GlobalAddAtom (atom_name);
+         win32_atom = GlobalAddAtom (atom_name);
          retval = GUINT_TO_POINTER ((guint) win32_atom);
        }
-      if (retval != GDK_NONE)
-       g_hash_table_insert (atom_hash, 
-                            g_strdup (atom_name), 
-                            retval);
+      g_hash_table_insert (atom_hash, 
+                          g_strdup (atom_name), 
+                          retval);
     }
 
   return retval;
@@ -87,8 +85,8 @@ gdk_atom_intern (const gchar *atom_name,
 gchar *
 gdk_atom_name (GdkAtom atom)
 {
-  gchar name[256];
   ATOM win32_atom;
+  gchar name[256];
 
   if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
   else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
@@ -134,6 +132,108 @@ gdk_property_get (GdkWindow   *window,
   return FALSE;
 }
 
+static gboolean
+find_common_locale (const guchar  *data,
+                   gint           nelements,
+                   gint           nchars,
+                   LCID          *lcidp,
+                   guchar       **bufp,
+                   gint          *sizep)
+{
+  static struct {
+    LCID lcid;
+    UINT cp;
+  } locales[] = {
+#define ENTRY(lang, sublang) \
+ { MAKELCID (MAKELANGID (LANG_##lang, SUBLANG_##sublang), SORT_DEFAULT), 0 }
+    ENTRY (ENGLISH, DEFAULT),
+    ENTRY (POLISH, DEFAULT),
+    ENTRY (CZECH, DEFAULT),
+    ENTRY (LITHUANIAN, DEFAULT),
+    ENTRY (RUSSIAN, DEFAULT),
+    ENTRY (GREEK, DEFAULT),
+    ENTRY (TURKISH, DEFAULT),
+    ENTRY (HEBREW, DEFAULT),
+    ENTRY (ARABIC, DEFAULT),
+    ENTRY (THAI, DEFAULT),
+    ENTRY (JAPANESE, DEFAULT),
+    ENTRY (CHINESE, CHINESE_SIMPLIFIED),
+    ENTRY (CHINESE, CHINESE_TRADITIONAL),
+    ENTRY (KOREAN, DEFAULT),
+#undef ENTRY
+  };
+
+  static gboolean been_here = FALSE;
+  gint i;
+  wchar_t *wcs;
+
+  /* For each installed locale: Get the locale's default code page,
+   * and store the list of locales and code pages.
+   */
+  if (!been_here)
+    {
+      been_here = TRUE;
+      for (i = 0; i < G_N_ELEMENTS (locales); i++)
+       if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
+         {
+           gchar buf[10];
+           if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
+                              buf, sizeof (buf)))
+             {
+               gchar name[100];
+               locales[i].cp = atoi (buf);
+               GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
+                                              LOCALE_SENGLANGUAGE,
+                                              name, sizeof (name)),
+                               g_print ("locale %#lx: %s: CP%d\n",
+                                        (gulong) locales[i].lcid, name,
+                                        locales[i].cp)));
+             }
+         }
+    }
+  
+  /* Allocate bufp big enough to store data in any code page.  Two
+   * bytes for each Unicode char should be enough, Windows code pages
+   * are either single- or double-byte.
+   */
+  *bufp = g_malloc ((nchars+1) * 2);
+  wcs = g_new (wchar_t, nchars+1);
+
+  /* Convert to Windows wide chars into temp buf */
+  _gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
+  wcs[nchars] = 0;
+
+  /* For each code page that is the default for an installed locale: */
+  for (i = 0; i < G_N_ELEMENTS (locales); i++)
+    {
+      BOOL used_default;
+      int nbytes;
+
+      if (locales[i].cp == 0)
+       continue;
+
+      /* Convert to that code page into bufp */
+      
+      nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
+                                   *bufp, (nchars+1)*2,
+                                   NULL, &used_default);
+
+      if (!used_default)
+       {
+         /* This locale is good for the string */
+         g_free (wcs);
+         *lcidp = locales[i].lcid;
+         *sizep = nbytes;
+         return TRUE;
+       }
+    }
+
+  g_free (*bufp);
+  g_free (wcs);
+
+  return FALSE;
+}
+
 void
 gdk_property_change (GdkWindow    *window,
                     GdkAtom       property,
@@ -143,10 +243,17 @@ gdk_property_change (GdkWindow    *window,
                     const guchar *data,
                     gint          nelements)
 {
-  HGLOBAL hdata;
-  gint i, length;
+  HGLOBAL hdata, hlcid, hutf8;
+  UINT cf = 0;
+  LCID lcid;
+  LCID *lcidptr;
+  GString *rtf = NULL;
+  gint i, size, nchars;
   gchar *prop_name, *type_name;
-  guchar *ptr;
+  guchar *ucptr, *buf = NULL;
+  wchar_t *wcptr;
+  enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
+  gboolean ok = TRUE;
 
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -154,7 +261,7 @@ gdk_property_change (GdkWindow    *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (prop_name = gdk_atom_name (property),
             type_name = gdk_atom_name (type),
             g_print ("gdk_property_change: %#x %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
@@ -174,40 +281,178 @@ gdk_property_change (GdkWindow    *window,
       && format == 8
       && mode == GDK_PROP_MODE_REPLACE)
     {
-      length = nelements;
-      for (i = 0; i < nelements; i++)
-       if (data[i] == '\n')
-         length++;
-#if 1      
-      GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n",
-                              (guint) GDK_WINDOW_HWND (window)));
       if (!OpenClipboard (GDK_WINDOW_HWND (window)))
        {
          WIN32_API_FAILED ("OpenClipboard");
          return;
        }
-#endif
-      hdata = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, length + 1);
-      ptr = GlobalLock (hdata);
-      GDK_NOTE (MISC, g_print ("...hdata=%#x, ptr=%p\n", (guint) hdata, ptr));
 
+      /* Check if only ASCII */
       for (i = 0; i < nelements; i++)
+       if (data[i] >= 0200)
+         break;
+
+      if (i == nelements)
+       nchars = nelements;
+      else
+       nchars = g_utf8_strlen (data, nelements);
+
+      GDK_NOTE (DND, g_print ("...nchars:%d\n", nchars));
+      
+      if (i == nelements)
+       {
+         /* If only ASCII, use CF_TEXT and the data as such. */
+         method = PLAIN_ASCII;
+         size = nelements;
+         for (i = 0; i < nelements; i++)
+           if (data[i] == '\n')
+             size++;
+         size++;
+         GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
+       }
+      else if (IS_WIN_NT ())
+       {
+         /* On NT, use CF_UNICODETEXT if any non-ASCII char present */
+         method = UNICODE_TEXT;
+         size = (nchars + 1) * 2;
+         GDK_NOTE (DND, g_print ("...as Unicode\n"));
+       }
+      else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
+       {
+         /* On Win9x, if all chars are in the default code page of
+          * some installed locale, use CF_TEXT and CF_LOCALE.
+          */
+         method = SINGLE_LOCALE;
+         GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
+                                 (gulong) lcid, size));
+       }
+      else
+       {
+         /* On Win9x, otherwise use RTF */
+
+         const guchar *p = data;
+
+         method = RICH_TEXT;
+         rtf = g_string_new ("{\\rtf1\\uc0 ");
+
+         while (p < data + nelements)
+           {
+             if (*p == '{' ||
+                 *p == '\\' ||
+                 *p == '}')
+               {
+                 rtf = g_string_append_c (rtf, '\\');
+                 rtf = g_string_append_c (rtf, *p);
+                 p++;
+               }
+             else if (*p < 0200)
+               {
+                 rtf = g_string_append_c (rtf, *p);
+                 p++;
+               }
+             else
+               {
+                 guchar *q;
+                 gint n;
+                 
+                 rtf = g_string_append (rtf, "\\uNNNNN ");
+                 rtf->len -= 6; /* five digits and a space */
+                 q = rtf->str + rtf->len;
+                 n = sprintf (q, "%d ", g_utf8_get_char (p));
+                 g_assert (n <= 6);
+                 rtf->len += n;
+                 
+                 p = g_utf8_next_char (p);
+               }
+           }
+         rtf = g_string_append (rtf, "}");
+         size = rtf->len + 1;
+         GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
+       }
+         
+      if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
        {
-         if (*data == '\n')
-           *ptr++ = '\r';
-         *ptr++ = *data++;
+         WIN32_API_FAILED ("GlobalAlloc");
+         if (!CloseClipboard ())
+           WIN32_API_FAILED ("CloseClipboard");
+         if (buf != NULL)
+           g_free (buf);
+         if (rtf != NULL)
+           g_string_free (rtf, TRUE);
+         return;
+       }
+
+      ucptr = GlobalLock (hdata);
+
+      switch (method)
+       {
+       case PLAIN_ASCII:
+         cf = CF_TEXT;
+         for (i = 0; i < nelements; i++)
+           {
+             if (*data == '\n')
+               *ucptr++ = '\r';
+             *ucptr++ = data[i];
+           }
+         *ucptr++ = '\0';
+         break;
+
+       case UNICODE_TEXT:
+         cf = CF_UNICODETEXT;
+         wcptr = (wchar_t *) ucptr;
+         if (_gdk_utf8_to_ucs2 (wcptr, data, nelements, nchars) == -1)
+           g_warning ("_gdk_utf8_to_ucs2() failed");
+         wcptr[nchars] = 0;
+         break;
+
+       case SINGLE_LOCALE:
+         cf = CF_TEXT;
+         memmove (ucptr, buf, size);
+         g_free (buf);
+
+         /* Set the CF_LOCALE clipboard data, too */
+         if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
+           WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
+         if (ok)
+           {
+             lcidptr = GlobalLock (hlcid);
+             *lcidptr = lcid;
+             GlobalUnlock (hlcid);
+             if (!SetClipboardData (CF_LOCALE, hlcid))
+               WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
+           }
+         break;
+
+       case RICH_TEXT:
+         cf = cf_rtf;
+         memmove (ucptr, rtf->str, size);
+         g_string_free (rtf, TRUE);
+
+         /* Set the UTF8_STRING clipboard data, too, for other
+          * GTK+ apps to use (won't bother reading RTF).
+          */
+         if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
+           WIN32_API_FAILED ("GlobalAlloc");
+         else
+           {
+             guchar *utf8ptr = GlobalLock (hutf8);
+             memmove (utf8ptr, data, nelements);
+             GlobalUnlock (hutf8);
+             if (!SetClipboardData (cf_utf8_string, hutf8))
+               WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
+           }
+         break;
+
+       default:
+         g_assert_not_reached ();
        }
-      *ptr++ = '\0';
+
       GlobalUnlock (hdata);
-      GDK_NOTE (MISC, g_print ("...SetClipboardData(CF_TEXT, %#x)\n",
-                              (guint) hdata));
-      if (!SetClipboardData(CF_TEXT, hdata))
-       WIN32_API_FAILED ("SetClipboardData");
-#if 1
-      GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
+      if (ok && !SetClipboardData (cf, hdata))
+       WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
+      
       if (!CloseClipboard ())
        WIN32_API_FAILED ("CloseClipboard");
-#endif
     }
   else
     g_warning ("gdk_property_change: General case not implemented");
@@ -222,7 +467,7 @@ gdk_property_delete (GdkWindow *window,
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (prop_name = gdk_atom_name (property),
             g_print ("gdk_property_delete: %#x %#x (%s)\n",
                      (window ? (guint) GDK_WINDOW_HWND (window) : 0),
index 1e53eefa2fedb2477121dcb75e2567689cbe726e..c8e6174c8b31d39a1a53047d2cfd25614f57e783 100644 (file)
@@ -1,5 +1,6 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1998-2002 Tor Lillqvist
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  */
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "gdkproperty.h"
 #include "gdkselection.h"
 #include "gdkprivate-win32.h"
 
-/* We emulate the GDK_SELECTION window properties by storing
- * it's data in a per-window hashtable.
+/* We emulate the GDK_SELECTION window properties of windows (as used
+ * in the X11 backend) by using a hash table from GdkWindows to
+ * GdkSelProp structs.
  */
 
 typedef struct {
@@ -43,11 +46,18 @@ typedef struct {
 
 static GHashTable *sel_prop_table = NULL;
 
+static GdkSelProp *dropfiles_prop = NULL;
+
+/* We store the owner of each selection in this table. Obviously, this only
+ * is valid intra-app, and in fact it is necessary for the intra-app DND to work.
+ */
+static GHashTable *sel_owner_table = NULL;
+
 void
 _gdk_win32_selection_init (void)
 {
-  if (sel_prop_table == NULL)
-    sel_prop_table = g_hash_table_new (g_int_hash, g_int_equal);
+  sel_prop_table = g_hash_table_new (NULL, NULL);
+  sel_owner_table = g_hash_table_new (NULL, NULL);
 }
 
 void
@@ -59,18 +69,42 @@ _gdk_selection_property_store (GdkWindow *owner,
 {
   GdkSelProp *prop;
 
-  prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (owner));
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
   if (prop != NULL)
     {
       g_free (prop->data);
-      g_hash_table_remove (sel_prop_table, &GDK_WINDOW_HWND (owner));
+      g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
     }
   prop = g_new (GdkSelProp, 1);
   prop->data = data;
   prop->length = length;
   prop->format = format;
   prop->type = type;
-  g_hash_table_insert (sel_prop_table, &GDK_WINDOW_HWND (owner), prop);
+  g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
+}
+
+void
+_gdk_dropfiles_store (gchar *data)
+{
+  if (data != NULL)
+    {
+      g_assert (dropfiles_prop == NULL);
+
+      dropfiles_prop = g_new (GdkSelProp, 1);
+      dropfiles_prop->data = data;
+      dropfiles_prop->length = strlen (data);
+      dropfiles_prop->format = 8;
+      dropfiles_prop->type = text_uri_list;
+    }
+  else
+    {
+      if (dropfiles_prop != NULL)
+       {
+         g_free (dropfiles_prop->data);
+         g_free (dropfiles_prop);
+       }
+      dropfiles_prop = NULL;
+    }
 }
 
 gboolean
@@ -79,24 +113,27 @@ gdk_selection_owner_set (GdkWindow *owner,
                         guint32    time,
                         gboolean   send_event)
 {
-  gchar *sel_name;
   HWND xwindow;
+  GdkEvent tmp_event;
+  gchar *sel_name;
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (sel_name = gdk_atom_name (selection),
             g_print ("gdk_selection_owner_set: %#x %#x (%s)\n",
                      (owner ? (guint) GDK_WINDOW_HWND (owner) : 0),
                      (guint) selection, sel_name),
             g_free (sel_name)));
 
-  if (selection != gdk_clipboard_atom)
+  if (selection != GDK_SELECTION_CLIPBOARD)
     {
-      if (!owner)
-        return FALSE;
-      _gdk_selection_property_store (owner, selection, 0, 0, 0);
+      if (owner != NULL)
+       g_hash_table_insert (sel_owner_table, selection, GDK_WINDOW_HWND (owner));
+      else
+       g_hash_table_remove (sel_owner_table, selection);
       return TRUE;
     }
 
+  /* Rest of this function handles the CLIPBOARD selection */
   if (owner != NULL)
     {
       if (GDK_WINDOW_DESTROYED (owner))
@@ -107,13 +144,11 @@ gdk_selection_owner_set (GdkWindow *owner,
   else
     xwindow = NULL;
 
-  GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n", (guint) xwindow));
   if (!OpenClipboard (xwindow))
     {
       WIN32_API_FAILED ("OpenClipboard");
       return FALSE;
     }
-  GDK_NOTE (MISC, g_print ("...EmptyClipboard()\n"));
   if (!EmptyClipboard ())
     {
       WIN32_API_FAILED ("EmptyClipboard");
@@ -125,74 +160,52 @@ gdk_selection_owner_set (GdkWindow *owner,
   if (xwindow != NULL)
     SetClipboardData (CF_TEXT, NULL);
 #endif
-  GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
   if (!CloseClipboard ())
     {
       WIN32_API_FAILED ("CloseClipboard");
       return FALSE;
     }
+
   if (owner != NULL)
     {
-      /* Send ourselves an ersatz selection request message so that
-       * gdk_property_change will be called to store the clipboard data.
+      /* Send ourselves a selection request message so that
+       * gdk_property_change will be called to store the clipboard
+       * data.
        */
-      SendMessage (xwindow, gdk_selection_request_msg,
-                  GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)), 0);
+      GDK_NOTE (DND, g_print ("...sending GDK_SELECTION_REQUEST to ourselves\n"));
+      tmp_event.selection.type = GDK_SELECTION_REQUEST;
+      tmp_event.selection.window = owner;
+      tmp_event.selection.send_event = FALSE;
+      tmp_event.selection.selection = selection;
+      tmp_event.selection.target = GDK_TARGET_STRING;
+      tmp_event.selection.property = _gdk_selection_property;
+      tmp_event.selection.requestor = (guint32) xwindow;
+      tmp_event.selection.time = time;
+
+      gdk_event_put (&tmp_event);
     }
 
   return TRUE;
 }
 
-/* callback for g_hash_table_for_each */
-typedef struct {
-  GdkAtom         atom;
-  GdkNativeWindow hwnd;
-} SelectionAndHwnd;
-
-static void
-window_from_selection (gpointer key,
-                 gpointer value,
-                 gpointer user_data)
-{
-  GdkSelProp *selprop = (GdkSelProp *)value;  
-  SelectionAndHwnd *sah = (SelectionAndHwnd *) user_data;
-
-  if (selprop->type == sah->atom)
-    sah->hwnd = *(GdkNativeWindow*) key;
-}
-
 GdkWindow*
 gdk_selection_owner_get (GdkAtom selection)
 {
   GdkWindow *window;
   gchar *sel_name;
 
-#if 0
-  /* XXX Hmm, gtk selections seem to work best with this. This causes
-   * gtk to always get the clipboard contents from Windows, and not
-   * from the editable's own stashed-away copy.
-   */
-  return NULL;
-#else
-  /* HB: The above is no longer true with recent changes to get
-   * inter-app drag&drop working ...
+  /* Return NULL for CLIPBOARD, because otherwise cut&paste
+   * inside the same application doesn't work. We must pretend to gtk
+   * that we don't have the selection, so that we always fetch it from
+   * the Windows clipboard. See also comments in
+   * gdk_selection_send_notify().
    */
-  if (selection != gdk_clipboard_atom)
-    {
-      SelectionAndHwnd sah;
-      sah.atom = selection;
-      sah.hwnd = 0;
-      g_hash_table_foreach (sel_prop_table, window_from_selection, &sah);
+  if (selection == GDK_SELECTION_CLIPBOARD)
+    return NULL;
 
-      window = gdk_win32_handle_table_lookup (sah.hwnd);
-    }
-  else
-    window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetClipboardOwner ());
-
-#endif
+  window = gdk_window_lookup (g_hash_table_lookup (sel_owner_table, selection));
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (sel_name = gdk_atom_name (selection),
             g_print ("gdk_selection_owner_get: %#x (%s) = %#x\n",
                      (guint) selection, sel_name,
@@ -202,6 +215,27 @@ gdk_selection_owner_get (GdkAtom selection)
   return window;
 }
 
+static void
+generate_selection_notify (GdkWindow *requestor,
+                          GdkAtom    selection,
+                          GdkAtom    target,
+                          GdkAtom    property,
+                          guint32    time)
+{
+  GdkEvent tmp_event;
+
+  tmp_event.selection.type = GDK_SELECTION_NOTIFY;
+  tmp_event.selection.window = requestor;
+  tmp_event.selection.send_event = FALSE;
+  tmp_event.selection.selection = selection;
+  tmp_event.selection.target = target;
+  tmp_event.selection.property = property;
+  tmp_event.selection.requestor = 0;
+  tmp_event.selection.time = time;
+
+  gdk_event_put (&tmp_event);
+}
+
 void
 gdk_selection_convert (GdkWindow *requestor,
                       GdkAtom    selection,
@@ -209,15 +243,14 @@ gdk_selection_convert (GdkWindow *requestor,
                       guint32    time)
 {
   HGLOBAL hdata;
-  guchar *ptr, *data, *datap, *p;
-  guint i, length, slength;
+  GdkAtom property = _gdk_selection_property;
   gchar *sel_name, *tgt_name;
 
   g_return_if_fail (requestor != NULL);
   if (GDK_WINDOW_DESTROYED (requestor))
     return;
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (sel_name = gdk_atom_name (selection),
             tgt_name = gdk_atom_name (target),
             g_print ("gdk_selection_convert: %#x %#x (%s) %#x (%s)\n",
@@ -227,96 +260,188 @@ gdk_selection_convert (GdkWindow *requestor,
             g_free (sel_name),
             g_free (tgt_name)));
 
-  if (selection == gdk_clipboard_atom)
+  if (selection == GDK_SELECTION_CLIPBOARD &&
+      target == gdk_atom_intern ("TARGETS", FALSE))
+    {
+      /* He wants to know what formats are on the clipboard.  If there
+       * is some kind of text, tell him so.
+       */
+      if (!OpenClipboard (GDK_WINDOW_HWND (requestor)))
+       {
+         WIN32_API_FAILED ("OpenClipboard");
+         return;
+       }
+
+      if (IsClipboardFormatAvailable (CF_UNICODETEXT) ||
+         IsClipboardFormatAvailable (cf_utf8_string) ||
+         IsClipboardFormatAvailable (CF_TEXT))
+       {
+         GdkAtom *data = g_new (GdkAtom, 1);
+         *data = GDK_TARGET_STRING;
+         _gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
+                                        32, data, 1 * sizeof (GdkAtom));
+       }
+      else
+       property = GDK_NONE;
+    }
+  else if (selection == GDK_SELECTION_CLIPBOARD &&
+          (target == compound_text ||
+           target == GDK_TARGET_STRING))
     {
       /* Converting the CLIPBOARD selection means he wants the
        * contents of the clipboard. Get the clipboard data,
        * and store it for later.
        */
-      GDK_NOTE (MISC, g_print ("...OpenClipboard(%#x)\n",
-                              (guint) GDK_WINDOW_HWND (requestor)));
       if (!OpenClipboard (GDK_WINDOW_HWND (requestor)))
        {
          WIN32_API_FAILED ("OpenClipboard");
          return;
        }
 
-      GDK_NOTE (MISC, g_print ("...GetClipboardData(CF_TEXT)\n"));
-      if ((hdata = GetClipboardData (CF_TEXT)) != NULL)
+      /* Try various formats. First the simplest, CF_UNICODETEXT. */
+      if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
        {
+         wchar_t *ptr, *wcs, *p, *q;
+         guchar *data;
+         gint length, wclen;
+
          if ((ptr = GlobalLock (hdata)) != NULL)
            {
              length = GlobalSize (hdata);
              
-             GDK_NOTE (MISC, g_print ("...got data: %d bytes: %.10s\n",
-                                      length, ptr));
-             
-             slength = 0;
+             GDK_NOTE (DND, g_print ("...CF_UNICODETEXT: %d bytes\n",
+                                     length));
+
+             /* Strip out \r */
+             wcs = g_new (wchar_t, (length + 1) * 2);
              p = ptr;
-             for (i = 0; i < length; i++)
+             q = wcs;
+             wclen = 0;
+             while (*p)
                {
-                 if (*p == '\0')
-                   break;
-                 else if (*p != '\r')
-                   slength++;
+                 if (*p != '\r')
+                   {
+                     *q++ = *p;
+                     wclen++;
+                   }
                  p++;
                }
+
+             data = _gdk_ucs2_to_utf8 (wcs, wclen);
+             g_free (wcs);
              
-             data = datap = g_malloc (slength + 1);
-             p = ptr;
-             for (i = 0; i < length; i++)
+             _gdk_selection_property_store (requestor, target, 8,
+                                            data, strlen (data) + 1);
+             GlobalUnlock (hdata);
+           }
+       }
+      else if ((hdata = GetClipboardData (cf_utf8_string)) != NULL)
+       {
+         /* UTF8_STRING is a format we store ourselves when necessary */
+         guchar *ptr;
+         gint length;
+
+         if ((ptr = GlobalLock (hdata)) != NULL)
+           {
+             length = GlobalSize (hdata);
+             
+             GDK_NOTE (DND, g_print ("...UTF8_STRING: %d bytes: %.10s\n",
+                                     length, ptr));
+             
+             _gdk_selection_property_store (requestor, target, 8,
+                                            g_strdup (ptr), strlen (ptr) + 1);
+             GlobalUnlock (hdata);
+           }
+       }
+      else if ((hdata = GetClipboardData (CF_TEXT)) != NULL)
+       {
+         /* We must always assume the data can contain non-ASCII
+          * in either the current code page, or if there is CF_LOCALE
+          * data, in that locale's default code page.
+          */
+         HGLOBAL hlcid;
+         UINT cp = CP_ACP;
+         wchar_t *wcs, *wcs2, *p, *q;
+         guchar *ptr, *data;
+         gint length, wclen;
+
+         if ((ptr = GlobalLock (hdata)) != NULL)
+           {
+             length = GlobalSize (hdata);
+             
+             GDK_NOTE (DND, g_print ("...CF_TEXT: %d bytes: %.10s\n",
+                                      length, ptr));
+             
+             if ((hlcid = GetClipboardData (CF_LOCALE)) != NULL)
+               {
+                 gchar buf[10];
+                 LCID *lcidptr = GlobalLock (hlcid);
+                 if (GetLocaleInfo (*lcidptr, LOCALE_IDEFAULTANSICODEPAGE,
+                                    buf, sizeof (buf)))
+                   {
+                     cp = atoi (buf);
+                     GDK_NOTE (DND, g_print ("...CF_LOCALE: %#lx cp:%d\n",
+                                             *lcidptr, cp));
+                   }
+                 GlobalUnlock (hlcid);
+               }
+
+             wcs = g_new (wchar_t, length + 1);
+             wclen = MultiByteToWideChar (cp, 0, ptr, length,
+                                          wcs, length + 1);
+
+             /* Strip out \r */
+             wcs2 = g_new (wchar_t, wclen);
+             p = wcs;
+             q = wcs2;
+             wclen = 0;
+             while (*p)
                {
-                 if (*p == '\0')
-                   break;
-                 else if (*p != '\r')
-                   *datap++ = *p;
+                 if (*p != '\r')
+                   {
+                     *q++ = *p;
+                     wclen++;
+                   }
                  p++;
                }
-             *datap++ = '\0';
-             _gdk_selection_property_store (requestor, GDK_TARGET_STRING, 8,
-                                 data, strlen (data) + 1);
+             g_free (wcs);
+
+             data = _gdk_ucs2_to_utf8 (wcs2, wclen);
+             g_free (wcs2);
              
+             _gdk_selection_property_store (requestor, target, 8,
+                                            data, strlen (data) + 1);
              GlobalUnlock (hdata);
            }
        }
-      GDK_NOTE (MISC, g_print ("...CloseClipboard()\n"));
-      CloseClipboard ();
-
+      else
+       property = GDK_NONE;
 
-      /* Send ourselves an ersatz selection notify message so that we actually
-       * fetch the data.
-       */
-      SendMessage (GDK_WINDOW_HWND (requestor), gdk_selection_notify_msg, 
-                   GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)), 
-                   GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
+      CloseClipboard ();
     }
-  else if (selection == gdk_win32_dropfiles_atom)
+  else if (selection == gdk_win32_dropfiles)
     {
       /* This means he wants the names of the dropped files.
        * gdk_dropfiles_filter already has stored the text/uri-list
-       * data, tempoarily on gdk_root_parent's selection "property".
+       * data temporarily in dropfiles_prop.
        */
-      GdkSelProp *prop;
-
-      prop = g_hash_table_lookup (sel_prop_table,
-                                 &GDK_WINDOW_HWND (_gdk_parent_root));
-
-      if (prop != NULL)
+      if (dropfiles_prop != NULL)
        {
-         g_hash_table_remove (sel_prop_table,
-                              &GDK_WINDOW_HWND (_gdk_parent_root));
-         _gdk_selection_property_store (requestor, prop->type, prop->format,
-                             prop->data, prop->length);
-         g_free (prop);
-         SendMessage (GDK_WINDOW_HWND (requestor), gdk_selection_notify_msg, 
-                     GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)), 
-                     GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
+         _gdk_selection_property_store
+           (requestor, selection, dropfiles_prop->format,
+            dropfiles_prop->data, dropfiles_prop->length);
+         g_free (dropfiles_prop);
+         dropfiles_prop = NULL;
        }
     }
   else
-    {
-      g_warning ("gdk_selection_convert: General case not implemented");
-    }
+    property = GDK_NONE;
+
+  /* Generate a selection notify message so that we actually fetch
+   * the data (if property == _gdk_selection_property) or indicating failure
+   * (if property == GDK_NONE).
+   */
+  generate_selection_notify (requestor, selection, target, property, time);
 }
 
 gint
@@ -333,21 +458,24 @@ gdk_selection_property_get (GdkWindow  *requestor,
   if (GDK_WINDOW_DESTROYED (requestor))
     return 0;
   
-  GDK_NOTE (MISC, g_print ("gdk_selection_property_get: %#x\n",
+  GDK_NOTE (DND, g_print ("gdk_selection_property_get: %#x\n",
                           (guint) GDK_WINDOW_HWND (requestor)));
 
-  prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (requestor));
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
 
   if (prop == NULL)
     {
       *data = NULL;
       return 0;
     }
+
   *data = g_malloc (prop->length);
   if (prop->length > 0)
     memmove (*data, prop->data, prop->length);
+
   if (ret_type)
     *ret_type = prop->type;
+
   if (ret_format)
     *ret_format = prop->format;
 
@@ -359,14 +487,15 @@ _gdk_selection_property_delete (GdkWindow *window)
 {
   GdkSelProp *prop;
   
-  prop = g_hash_table_lookup (sel_prop_table, &GDK_WINDOW_HWND (window));
+  GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %#x\n",
+                          (guint) GDK_WINDOW_HWND (window)));
+
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
   if (prop != NULL)
     {
       g_free (prop->data);
-      g_hash_table_remove (sel_prop_table, &GDK_WINDOW_HWND (window));
+      g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (window));
     }
-  else
-    g_warning ("huh?");
 }
 
 void
@@ -376,9 +505,10 @@ gdk_selection_send_notify (guint32  requestor,
                           GdkAtom  property,
                           guint32  time)
 {
+  GdkEvent tmp_event;
   gchar *sel_name, *tgt_name, *prop_name;
 
-  GDK_NOTE (MISC,
+  GDK_NOTE (DND,
            (sel_name = gdk_atom_name (selection),
             tgt_name = gdk_atom_name (target),
             prop_name = gdk_atom_name (property),
@@ -394,23 +524,31 @@ gdk_selection_send_notify (guint32  requestor,
   /* Send ourselves a selection clear message so that gtk thinks we don't
    * have the selection, and will claim it anew when needed, and
    * we thus get a chance to store data in the Windows clipboard.
-   * Otherwise, if a gtkeditable does a copy to clipboard several times
+   * Otherwise, if a gtkeditable does a copy to CLIPBOARD several times
    * only the first one actually gets copied to the Windows clipboard,
-   * as only he first one causes a call to gdk_property_change.
+   * as only the first one causes a call to gdk_property_change().
    *
    * Hmm, there is something fishy with this. Cut and paste inside the
    * same app didn't work, the gtkeditable immediately forgot the
-   * clipboard contents in gtk_editable_selection_clear as a result of
-   * this message. OTOH, when I changed gdk_selection_owner_get to
-   * always return NULL, it works. Sigh.
+   * clipboard contents in gtk_editable_selection_clear() as a result
+   * of this message. OTOH, when I changed gdk_selection_owner_get to
+   * return NULL for CLIPBOARD, it works. Sigh.
    */
 
-  SendMessage ((HWND) requestor, 
-               gdk_selection_clear_msg, 
-               GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (selection)), 
-               GPOINTER_TO_UINT (GDK_ATOM_TO_POINTER (target)));
+  tmp_event.selection.type = GDK_SELECTION_CLEAR;
+  tmp_event.selection.window = gdk_window_lookup (requestor);
+  tmp_event.selection.send_event = FALSE;
+  tmp_event.selection.selection = selection;
+  tmp_event.selection.target = 0;
+  tmp_event.selection.property = 0;
+  tmp_event.selection.requestor = 0;
+  tmp_event.selection.time = time;
+
+  gdk_event_put (&tmp_event);
 }
 
+/* Simplistic implementations of text list and compound text functions */
+
 gint
 gdk_text_property_to_text_list (GdkAtom       encoding,
                                gint          format, 
@@ -418,10 +556,20 @@ gdk_text_property_to_text_list (GdkAtom       encoding,
                                gint          length,
                                gchar      ***list)
 {
-  GDK_NOTE (MISC,
-           g_print ("gdk_text_property_to_text_list not implemented\n"));
+  gchar *enc_name;
+
+  GDK_NOTE (DND, (enc_name = gdk_atom_name (encoding),
+                 g_print ("gdk_text_property_to_text_list: %s %d %.20s %d\n",
+                          enc_name, format, text, length),
+                 g_free (enc_name)));
+
+  if (!list)
+    return 0;
+
+  *list = g_new (gchar **, 1);
+  **list = g_strdup (text);
   
-  return 0;
+  return 1;
 }
 
 void
@@ -429,7 +577,8 @@ gdk_free_text_list (gchar **list)
 {
   g_return_if_fail (list != NULL);
 
-  /* ??? */
+  g_free (*list);
+  g_free (list);
 }
 
 gint
@@ -439,7 +588,19 @@ gdk_string_to_compound_text (const gchar *str,
                             guchar     **ctext,
                             gint        *length)
 {
-  g_warning ("gdk_string_to_compound_text: Not implemented");
+  GDK_NOTE (DND, g_print ("gdk_string_to_compound_text: %.20s\n", str));
+
+  if (encoding)
+    *encoding = compound_text;
+
+  if (format)
+    *format = 8;
+
+  if (ctext)
+    *ctext = g_strdup (str);
+
+  if (length)
+    *length = strlen (str);
 
   return 0;
 }
@@ -447,7 +608,7 @@ gdk_string_to_compound_text (const gchar *str,
 void
 gdk_free_compound_text (guchar *ctext)
 {
-  g_warning ("gdk_free_compound_text: Not implemented");
+  g_free (ctext);
 }
 
 /* These are lifted from gdkselection-x11.c, just to get GTK+ to build.
@@ -534,7 +695,7 @@ make_list (const gchar  *text,
  * @list:     location to store the list of strings or %NULL. The
  *            list should be freed with g_strfreev().
  * 
- * Convert a text property in the giving encoding to
+ * Converts a text property in the giving encoding to
  * a list of UTF-8 strings. 
  * 
  * Return value: the number of strings in the resulting
@@ -554,7 +715,7 @@ gdk_text_property_to_utf8_list (GdkAtom        encoding,
     {
       return make_list ((gchar *)text, length, TRUE, list);
     }
-  else if (encoding == gdk_atom_intern ("UTF8_STRING", FALSE))
+  else if (encoding == utf8_string)
     {
       return make_list ((gchar *)text, length, FALSE, list);
     }
@@ -563,8 +724,8 @@ gdk_text_property_to_utf8_list (GdkAtom        encoding,
       gchar **local_list;
       gint local_count;
       gint i;
-      gchar *charset = NULL;
-      gboolean need_conversion= g_get_charset (&charset);
+      const gchar *charset = NULL;
+      gboolean need_conversion = g_get_charset (&charset);
       gint count = 0;
       GError *error = NULL;
       
@@ -663,7 +824,7 @@ sanitize_utf8 (const gchar *src)
  * gdk_utf8_to_string_target:
  * @str: a UTF-8 string
  * 
- * Convert an UTF-8 string into the best possible representation
+ * Converts an UTF-8 string into the best possible representation
  * as a STRING. The representation of characters not in STRING
  * is not specified; it may be as pseudo-escape sequences
  * \x{ABCD}, or it may be in some other form of approximation.
@@ -675,21 +836,7 @@ sanitize_utf8 (const gchar *src)
 gchar *
 gdk_utf8_to_string_target (const gchar *str)
 {
-  GError *error = NULL;
-  
-  gchar *tmp_str = sanitize_utf8 (str);
-  gchar *result =  g_convert_with_fallback (tmp_str, -1,
-                                           "ISO-8859-1", "UTF-8",
-                                           NULL, NULL, NULL, &error);
-  if (!result)
-    {
-      g_warning ("Error converting from UTF-8 to STRING: %s",
-                error->message);
-      g_error_free (error);
-    }
-  
-  g_free (tmp_str);
-  return result;
+  return sanitize_utf8 (str);
 }
 
 /**
@@ -701,10 +848,10 @@ gdk_utf8_to_string_target (const gchar *str)
  * @length:   location to store the length of the data
  *            stored in @ctext
  * 
- * Convert from UTF-8 to compound text. 
+ * Converts from UTF-8 to compound text. 
  * 
  * Return value: %TRUE if the conversion succeeded, otherwise
- *               false.
+ *               %FALSE.
  **/
 gboolean
 gdk_utf8_to_compound_text (const gchar *str,
@@ -714,14 +861,14 @@ gdk_utf8_to_compound_text (const gchar *str,
                           gint        *length)
 {
   gboolean need_conversion;
-  gchar *charset;
+  const gchar *charset;
   gchar *locale_str, *tmp_str;
   GError *error = NULL;
   gboolean result;
 
   g_return_val_if_fail (str != NULL, FALSE);
 
-  need_conversion = g_get_charset (&charset);
+  need_conversion = !g_get_charset (&charset);
 
   tmp_str = sanitize_utf8 (str);
 
index a7467d3b80bdbf7a8da88c139305bce8567a26e0..c5562c3df522b43c5bfb3f5594ad9e639b00cdf4 100644 (file)
@@ -2422,7 +2422,7 @@ gdk_window_stick (GdkWindow *window)
       /* "stick" means stick to all desktops _and_ do not scroll with the
        * viewport. i.e. glue to the monitor glass in all cases.
        */
-      g_warning ("gdk_window_stick (0x%X) ???", GDK_WINDOW_HWND (window));
+      g_warning ("gdk_window_stick (%#x) ???", (guint) GDK_WINDOW_HWND (window));
     }
   else
     {
@@ -2443,7 +2443,7 @@ gdk_window_unstick (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     {
-      g_warning ("gdk_window_unstick (0x%X) ???", GDK_WINDOW_HWND (window));
+      g_warning ("gdk_window_unstick (%#x) ???", (guint) GDK_WINDOW_HWND (window));
     }
   else
     {
@@ -2451,7 +2451,6 @@ gdk_window_unstick (GdkWindow *window)
       gdk_synthesize_window_state (window,
                                    GDK_WINDOW_STATE_STICKY,
                                    0);
-
     }
 }
 
@@ -2555,8 +2554,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
    * XXX ???
    */
   GDK_NOTE (MISC,
-            g_print ("gdk_window_set_type_hint (0x%0X)\n",
-                     GDK_WINDOW_HWND (window)));
+            g_print ("gdk_window_set_type_hint (%#x)\n",
+                     (guint) GDK_WINDOW_HWND (window)));
 }
 
 void